package de.Niklas.Laser;

import de.Niklas.Laser.Listener.AimListener;
import de.Niklas.Laser.Listener.LaserListener;
import de.Niklas.Laser.util.ConfigUtil.Bundle;
import de.Niklas.Laser.util.ConfigUtil.ConfigGUI;
import de.Niklas.Laser.util.ConfigUtil.ConfigSetting;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

public class LaserPlugin extends JavaPlugin {
    public static String STRING_LASER;
    public static List<String> LORE_LASER;
    public static final String STRING_LASER_MUN;
    public static final String PERM_GET = "laser.get";
    public static final String PERM_GET_OTHER = "laser.get.other";
    public static final String PERM_USE = "laser.use";
    public static final String PERM_USE_BLOCKS = "laser.use.blocks";
    public static final String PERM_CONFIG = "laser.config";
    public FileConfiguration c;
    public ArrayList<String> imScope;
    HashMap<String, String> lang;
    public static boolean hasNCP;
    public static Logger LOGGER;
    public static LaserPlugin INSTANCE;

    static {
        LaserPlugin.STRING_LASER = ChatColor.translateAlternateColorCodes('&', "&4&l激光枪");
        LaserPlugin.LORE_LASER = new ArrayList<>();
        STRING_LASER_MUN = ChatColor.translateAlternateColorCodes('&', "&8激光枪子弹");
        LaserPlugin.hasNCP = false;
    }

    public LaserPlugin() {
        this.imScope = new ArrayList<>();
        this.lang = new HashMap<>();
    }

    public void onEnable() {
        LOGGER = getLogger();
        INSTANCE = this;
        INSTANCE.c = INSTANCE.getConfig();
        INSTANCE.c.options().copyDefaults(true);
        INSTANCE.saveConfig();
        try {
            INSTANCE.setupBundle();
        } catch (Exception e) {
            LOGGER.info("[Laser] - Error while setting up the options - please check your Config!");
        }
        INSTANCE.getServer().getPluginManager().registerEvents(new LaserListener(INSTANCE), INSTANCE);
        try {
            INSTANCE.getServer().getPluginManager().registerEvents(new ConfigGUI(INSTANCE), INSTANCE);
        } catch (Exception e) {
            LOGGER.severe("Error while enabling the config option GUI!");
            e.printStackTrace();
        }
        INSTANCE.getServer().getPluginManager().registerEvents(new AimListener(INSTANCE), INSTANCE);
        if (Bundle.OPTIONS_CRAFTABLEAMMO.value) {
            INSTANCE.setupMunCrafting();
        }
        if (Bundle.OPTIONS_CRAFTABLELASER.value) {
            INSTANCE.setupLaserCrafting();
        }
        INSTANCE.setupLang(INSTANCE.c.getString("options.language", "eng"));
        LaserPlugin.hasNCP = Bukkit.getPluginManager().isPluginEnabled("NoCheatPlus");
        if (LaserPlugin.hasNCP) {
            LOGGER.info("NCP found!");
        }
        LOGGER.info("Laser enabled!");
    }

    public void onDisable() {
        for (final String s : INSTANCE.imScope) {
            final Player p = INSTANCE.getServer().getPlayer(s);
            if (p == null) {
                continue;
            }
            INSTANCE.removeScopeEffects(p);
        }
        INSTANCE.imScope.clear();
        LaserPlugin.LOGGER.info("Laser has been disabled!");
    }

    public boolean onCommand(final CommandSender sender, final Command cmd, final String label, final String[] args) {
        if (cmd.getName().equalsIgnoreCase("laser")) {
            if (!(sender instanceof Player)) {
                sender.sendMessage(INSTANCE.getLangString(Message.consoleChatErrorMsg));
                return true;
            }
            if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
                if (!sender.hasPermission("laser.get")) {
                    sender.sendMessage(INSTANCE.getLangString(Message.noPermissionMsg));
                    return true;
                }
                try {
                    INSTANCE.setupBundle();
                    INSTANCE.lang.clear();
                    INSTANCE.setupLang(INSTANCE.c.getString("options.language", "eng"));
                } catch (Exception e2) {
                    LaserPlugin.LOGGER.info("[Laser] - Error while setting up the options - please check your Config!");
                }
                return true;
            } else {
                if (args.length == 1) {
                    if (!sender.hasPermission("laser.get")) {
                        sender.sendMessage(INSTANCE.getLangString(Message.noPermissionMsg));
                        return true;
                    }
                    final Player p = Bukkit.getPlayer(args[0]);
                    if (p != null) {
                        p.getInventory().addItem(INSTANCE.bekommeLaser());
                        final ItemStack mun = INSTANCE.bekommeMun();
                        mun.setAmount(32);
                        p.getInventory().addItem(mun);
                        p.sendMessage(INSTANCE.getLangString(Message.laserGetMsg));
                        return true;
                    }
                    sender.sendMessage(ChatColor.RED + "Player not found!");
                }
                final Player p = (Player) sender;
                if (!p.hasPermission("laser.get")) {
                    p.sendMessage(INSTANCE.getLangString(Message.noPermissionMsg));
                    return true;
                }
                p.getInventory().addItem(INSTANCE.bekommeLaser());
                final ItemStack mun = INSTANCE.bekommeMun();
                mun.setAmount(32);
                p.getInventory().addItem(mun);
                p.sendMessage(INSTANCE.getLangString(Message.laserGetMsg));
                return true;
            }
        } else if (cmd.getName().equalsIgnoreCase("laserammo")) {
            if (!(sender instanceof Player)) {
                sender.sendMessage(INSTANCE.getLangString(Message.consoleChatErrorMsg));
                return true;
            }
            final Player p = (Player) sender;
            if (!p.hasPermission("laser.get")) {
                p.sendMessage(INSTANCE.getLangString(Message.noPermissionMsg));
                return true;
            }
            final ItemStack mun = INSTANCE.bekommeMun();
            if (args.length == 0) {
                mun.setAmount(32);
                p.getInventory().addItem(mun);
            } else {
                try {
                    int amount = Integer.parseInt(args[0]);
                    if (amount <= 64) {
                        mun.setAmount(amount);
                        p.getInventory().addItem(mun);
                    } else {
                        while (amount > 64) {
                            mun.setAmount(64);
                            p.getInventory().addItem(mun);
                            amount -= 64;
                        }
                        mun.setAmount(amount);
                        p.getInventory().addItem(mun);
                    }
                } catch (NumberFormatException e3) {
                    p.sendMessage(ChatColor.RED + "/laserammo [Amount]");
                }
            }
            p.sendMessage(INSTANCE.getLangString(Message.laserGetMsg));
            return true;
        } else {
            if (!cmd.getName().equalsIgnoreCase("laserconfig")) {
                return false;
            }
            if (!(sender instanceof Player)) {
                sender.sendMessage(INSTANCE.getLangString(Message.consoleChatErrorMsg));
                return true;
            }
            final Player p = (Player) sender;
            if (!sender.hasPermission("laser.config")) {
                sender.sendMessage(INSTANCE.getLangString(Message.noPermissionMsg));
                return true;
            }
            try {
                ConfigGUI.openCompleteGUI(p);
            } catch (Exception e) {
                p.sendMessage("Error!");
                e.printStackTrace();
            }
            return true;
        }
    }

    public ItemStack bekommeLaser() {
        final ItemStack is = new ItemStack(Material.getMaterial(INSTANCE.c.getInt("options.id", 356)), 1);
        final ItemMeta im = is.getItemMeta();
        im.setDisplayName(LaserPlugin.STRING_LASER);
        im.setLore(LaserPlugin.LORE_LASER);
        is.setItemMeta(im);
        return is;
    }

    public ItemStack bekommeMun() {
        final ItemStack is = new ItemStack(Material.REDSTONE, 1);
        final ItemMeta im = is.getItemMeta();
        im.setDisplayName(LaserPlugin.STRING_LASER_MUN);
        im.setLore(Collections.singletonList(ChatColor.DARK_GRAY + "激光枪也是需要补充能量的"));
        is.setItemMeta(im);
        return is;
    }

    private void setupDefaultLaserCrafting() {
        final ItemStack laser = INSTANCE.bekommeLaser();
        final ShapedRecipe laserrecipe = new ShapedRecipe(new NamespacedKey(INSTANCE, "LaserRecipe"), laser);
        laserrecipe.shape("SSS", "RNR", "SSS");
        laserrecipe.setIngredient('S', Material.STONE);
        laserrecipe.setIngredient('R', Material.REDSTONE);
        laserrecipe.setIngredient('N', Material.NETHER_STAR);
        INSTANCE.getServer().addRecipe(laserrecipe);
    }

    private void setupLaserCrafting() {
        try {
            final ItemStack laser = INSTANCE.bekommeLaser();
            final ShapedRecipe laserrecipe = new ShapedRecipe(new NamespacedKey(INSTANCE, "LaserRecipe"), laser);
            laserrecipe.shape("012", "345", "678");
            final List<String> mats = INSTANCE.c.getStringList("options.crafting");
            for (int i = 0; i < 9; ++i) {
                if (Material.valueOf(mats.get(i + 1)) != Material.AIR) {
                    laserrecipe.setIngredient(String.valueOf(i).toCharArray()[0], Material.valueOf(mats.get(i + 1)));
                }
            }
            INSTANCE.getServer().addRecipe(laserrecipe);
        } catch (Exception e) {
            INSTANCE.setupDefaultLaserCrafting();
            LaserPlugin.LOGGER.info("No custom crafting recipe found, enabling default one");
        }
    }

    private void setupDefaultMunCrafting() {
        final ItemStack mun = INSTANCE.bekommeMun();
        mun.setAmount(8);
        final ShapelessRecipe munrecipe = new ShapelessRecipe(new NamespacedKey(INSTANCE, "MunRecipe"),mun);
        munrecipe.addIngredient(8, Material.REDSTONE);
        munrecipe.addIngredient(Material.SULPHUR);
        INSTANCE.getServer().addRecipe(munrecipe);
    }

    private void setupMunCrafting() {
        try {
            final ItemStack ammo = INSTANCE.bekommeMun();
            final ShapedRecipe munrecipe = new ShapedRecipe(new NamespacedKey(INSTANCE, "MunRecipe"),ammo);
            munrecipe.shape("012", "345", "678");
            final List<String> mats = INSTANCE.c.getStringList("options.ammocrafting");
            for (int i = 0; i < 9; ++i) {
                if (Material.valueOf(mats.get(i + 1)) != Material.AIR) {
                    munrecipe.setIngredient(String.valueOf(i).toCharArray()[0], Material.valueOf(mats.get(i + 1)));
                }
            }
            INSTANCE.getServer().addRecipe(munrecipe);
        } catch (Exception e) {
            INSTANCE.setupDefaultMunCrafting();
            LaserPlugin.LOGGER.info("No custom ammo crafting recipe found, enabling default one");
        }
    }

    public void setupLang(final String language) {
        final Map<String, Object> configValues = INSTANCE.c.getValues(true);
        for (final Map.Entry<String, Object> set : configValues.entrySet()) {
            if (!set.getKey().startsWith("lang." + language + ".")) {
                continue;
            }
            final String messageIdString = set.getKey().split("\\.")[2];
            INSTANCE.lang.put(messageIdString, String.valueOf(set.getValue()));
        }
    }

    public String getLangString(final Message m) {
        return ChatColor.translateAlternateColorCodes('&', INSTANCE.lang.get(m.name()));
    }

    public void setupBundle() {
        for (Field f : Bundle.class.getFields()) {
            final String configName = f.getName().replace('_', '.').toLowerCase();
            try {
                ((ConfigSetting) f.get(null)).setValue(INSTANCE.c.get(configName));
            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.severe(ChatColor.RED + "at " + configName);
            }
        }
    }

    public void addScope(final Player p) {
        if (!INSTANCE.imScope.contains(p.getName())) {
            INSTANCE.imScope.add(p.getName());
            p.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 90001, 127, true), true);
            p.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 90001, 128, true), true);
            p.getWorld().playSound(p.getLocation(), Sound.BLOCK_FIRE_AMBIENT, 1.0f, 2.0f);
        }
    }

    public void removeScope(final Player p) {
        if (INSTANCE.imScope.contains(p.getName())) {
            INSTANCE.imScope.remove(p.getName());
            p.removePotionEffect(PotionEffectType.SLOW);
            p.removePotionEffect(PotionEffectType.JUMP);
            p.playSound(p.getLocation(), Sound.BLOCK_FIRE_AMBIENT, 1.0f, 2.0f);
        }
    }

    public void removeScopeEffects(final Player p) {
        if (INSTANCE.imScope.contains(p.getName())) {
            p.removePotionEffect(PotionEffectType.SLOW);
            p.removePotionEffect(PotionEffectType.JUMP);
            p.playSound(p.getLocation(), Sound.BLOCK_FIRE_AMBIENT, 1.0f, 2.0f);
        }
    }

    public boolean imScope(final Player p) {
        return INSTANCE.imScope.contains(p.getName());
    }

    public enum Message {
        consoleChatErrorMsg("consoleChatErrorMsg", 0),
        noPermissionMsg("noPermissionMsg", 1),
        laserGetMsg("laserGetMsg", 2),
        configValueMsg("configValueMsg", 3),
        configValueErrorMsg("configValueErrorMsg", 4),
        configValueSuccessMsg("configValueSuccessMsg", 5),
        configValueListMsg("configValueListMsg", 6),
        configValueGuiUpdated("configValueGuiUpdated", 7),
        laserAmmoNeeded("laserAmmoNeeded", 8),
        laserCooling("laserCooling", 9);

        Message(final String s, final int n) {
        }
    }
}
